package org.myorg.v4;



public class Moutain {
	public static void main(String args[]) {
		int ln = 100;
		
		double mit = 0;
		double mrt = 0;
		
		
		String recordtime = "";
		
		String recordit = "";
		

		
		for(int i = 0; i < ln; i++) {
			long st = System.currentTimeMillis();
			double it = ga();
			
			if (i%10 == 0)
				System.out.println(i + " completed");
			
			long rt = System.currentTimeMillis() - st;
			
			
			mit = mit + it;
			mrt = mrt + rt;
			recordit = recordit + "\t" + it;
			recordtime = recordtime + "\t" + rt;
			
			System.out.println("sum of iterator time is "+ it);
			System.out.println("time is "+ rt);
		}
		
		String res = "iterator: " + recordit + "\n" + "time: " + recordtime + 
		"\n" + "sum iterator: " + mit + "\n" +"sum time: " + mrt;
		
		RWF4.wlf(res.getBytes(), "res/moutian");
		
		System.out.println("sum of iterator time is "+ mit);
		
	}
	
	public static long ga() {
		int best_p = 0;
		long it = 0;
		double best_v = 0;
		People my_p = new People(200,63);
		Evolution my_e = new Evolution(0.1, 0.2, 0.1, my_p);
		
		for (long i=0; i < Long.MAX_VALUE; i++) {
			my_p.caculateFitness();
			my_e.select();
			my_e.crossOver();
			my_e.mutation();
			
			best_p = my_p.getBest();
			best_v = Function.caculate(my_p.getPeople()[best_p]);
			it++;
			if((1 - best_v) < 1.0E-05) {
				break;
			}
			//System.out.println("the best value is "+best_v);
		}
		
	
		System.out.println("the best individual is "+my_p.getPeople()[best_p]);
		System.out.println("the best value is "+best_v);
		System.out.println("iterator time is "+ it);
		return it;
	}
}

/*class Function {
	static public double caculate(String person) {
		double res = 0;
		*//**
		 * add your function here
		 * for example: f(x)= sin(x) x [0, 3.14] 
		 * set the genetic length is 20, so the mapping relation is
		 * [0, 2^20] -> [0, 3.14]
		 *//*
		int tem = Integer.parseInt(person, 2);
		double x = tem*3.14/(Math.pow(2, person.length()));
		res = Math.cos(x)+Math.sin(x);
		return res;
	}
	static public boolean better(double a, double b) {
		return a<b?true:false;
	}
}
*/
class Function {
/*	static public double caculate(String person) {
		double res = 0;
		*//**
		 * add your function here
		 * for example: f(x)= sin(x) x [0, 3.14] 
		 * set the genetic length is 20, so the mapping relation is
		 * [0, 2^20] -> [0, 3.14]
		 *//*
		int tem = Integer.parseInt(person, 2);
		//double x = tem*3.14/(Math.pow(2, person.length()));
		//res = Math.cos(x)+Math.sin(x);
		double N = Math.pow(2, person.length()) -1;
		if (tem != 0)
			res = (N - (double)tem)/(N-1);
		else
			res = -1;
		return res;
	}*/
	
	static public double caculate(String person) {
		double res = 0;
		/**
		 * add your function here
		 * for example: f(x)= sin(x) x [0, 3.14] 
		 * set the genetic length is 20, so the mapping relation is
		 * [0, 2^20] -> [0, 3.14]
		 */
		double N = 20;
		//Integer.parseInt(person, 2);
		double tem = Long.parseLong(person, 2);
		double scope = Math.pow(2, person.length()) - 1;
		//double N = scope;
		double x = tem*N/scope;
		//res = Math.cos(x)+Math.sin(x);
		//double N = Math.pow(2, person.length()) -1;
		if (x > 1)
			res = -(1d/6d)*x+(7d/6d);
		else
			res = 2*x - 1;
		
		//System.out.println("tem: " + tem + " scope: " + scope + " x: " + x + " res: " + res );
		return res;
	}
	static public boolean better(double a, double b) {
		return a>b?true:false;
	}
}

class People {
	public int p_num;
	public int p_length;
	private String persons[];
	private double fitness[];
	
	public People(People people) {
		this.persons = people.persons;
		this.fitness = people.fitness;
	}
	
	public People(int num, int length) {
		p_num = num;
		p_length = length;
		fitness = new double[num];
		persons = new String[num];
				
		for(int i = 0; i < num; i++) {
			persons[i] = "";
			for(int j = 0; j < length; j++) {
				if (Math.random() > 0.5) {
					persons[i] += "0";
				} else {
					persons[i] += "1";
				}
			}
		}
		//System.out.println(persons[0]);
	}
	
	public void caculateFitness() {
		for (int i = 0; i < p_num; i++) {
			fitness[i] = Function.caculate(persons[i]);
		}
	}
	
	public int getBest() {
		int res = 0;
		for (int i = 0; i<p_num; i++) {
			if(Function.better(fitness[i],fitness[res]))
				res = i;
		}
		return res;
	}
	
	public double[] getFitness() {
		return fitness;
	}
	
	public String[] getPeople() {
		return persons;
	}
	
}

class Evolution {
	/*
	 * 
	 * @param p_s 选择算子
	 * @param p_c 交叉算子 
	 * @param p_m 变异算子
	 */
	private double ps;
	private double pc;
	private double pm;
	private People people;
	
	public Evolution(double p_s, double p_c, double p_m, People p) {
		ps = p_s;
		pc = p_c;
		pm = p_m;
		people = p;
	}
	
	/*
	 * 使用锦标赛的选择算法
	 */
	public void select() {
		for (int i = 0; i < people.p_num; i++) {
			int pos1 = (int) (Math.random()*people.p_num);
			int pos2 = (int) (Math.random()*people.p_num);
			if (Function.better(people.getFitness()[pos1], people.getFitness()[pos2]))
				people.getPeople()[i] = people.getPeople()[pos1];
			else
				people.getPeople()[i] = people.getPeople()[pos2];
			
		}
	}
	/*
	 * 交叉
	 */
	public void crossOver() {
		for (int i=0; i < (int) (pc*people.p_num); i++) {
			int pos1 = (int) (Math.random()*people.p_num);
			int pos2 = (int) (Math.random()*people.p_num);
			int cross_pos = (int) (Math.random()*people.p_length);
			
			String temp1 = people.getPeople()[pos1].substring(0,cross_pos)
			+people.getPeople()[pos2].substring(cross_pos);

			people.getPeople()[pos2] = people.getPeople()[pos2].substring(0,cross_pos)
			+people.getPeople()[pos1].substring(cross_pos);
			
			people.getPeople()[pos1] = temp1;
			
		}
	}
	
	/*
	 * 变异
	 */
	
	public void mutation() {
		//for(int i = 0; i < people.p_num; i++) {
		int i = 0;
		if(Math.random() > 0.5)
			i = 1;
			for(int j = 0; j < people.p_length; j++) {
				if (Math.random() < pm) {
					char temp[]; 
					
					if (people.getPeople()[i].charAt(j) == '0') {
						temp = people.getPeople()[i].toCharArray();
						temp[j] = '1';
						people.getPeople()[i] = new String(temp);
					} else {
						temp = people.getPeople()[i].toCharArray();
						temp[j] = '0';
						people.getPeople()[i] = new String(temp);
					}
				}
			}
		//}
	}
	
/*	public void mutation() {
		for(int i = 0; i < (int) (pm*people.p_num); i++) {
			int pos = (int) (Math.random()*people.p_num);
			int mut_pos = (int) (Math.random()*people.p_length);
			char temp[]; 
				
			if (people.getPeople()[pos].charAt(mut_pos) == '0') {
				temp = people.getPeople()[pos].toCharArray();
				temp[mut_pos] = '1';
				people.getPeople()[pos] = new String(temp);
			} else {
				temp = people.getPeople()[pos].toCharArray();
				temp[mut_pos] = '0';
				people.getPeople()[pos] = new String(temp);
			}
		}
	}*/
	
	
}
